import axios from 'axios';
import { accessSync, constants  } from 'node:fs';
import { readFile } from 'node:fs/promises';
import Cookies from 'js-cookie';
import gateway from "./circle-gateway.js";

/**
 * @type string
 */
export const COOKIE_KEY = "userLoginInfo";

let NODE_ENV = "production";

export function setNodeEnv(env) {
  NODE_ENV = env;
}

/**
 * build url tool
 * @param {string} path - the relative path
 * @param {Record<string, Object>} params - the parameter map.
 * @returns {string} - the final url.
 */
export function buildUrl(path, params={}) {
  let host = gateway.http.host;
  let protocol = gateway.http.protocol;
  if (NODE_ENV !== "production") {
    host = "localhost:8888";
    protocol = "http";
  }
  let url = `${protocol}://${host}${path}`;
  if (params) {
    const entries = Object.entries(params);
    if (entries.length > 0) {
      const urlParams = entries.map((entry) => `${entry[0]}=${encodeURIComponent(entry[1])}`);
      url = `${url}?${urlParams.join('&')}`;
    }
  }
  console.log("buildUrl:", url);
  return url;
}

/**
 * @template T
 * @template {{ status: number, data: T, message: string}} Response
 * post data by application/json content type.
 * @param {string} url - the post url.
 * @param {Object} input - the input
 * @param {number} [timeout] - the timeout.
 * @returns {Promise<Response>} - the post result.
 */
export async function postData(url, input, timeout=30000) {
  try {
    const headers = {
      'Content-Type': 'application/json',
    };
    const authorization = await getSessionKey();
    if (authorization) {
      headers['AuthorizationV2'] = authorization;
    }
    const response = await axios.post(url, input, {
      headers,
      timeout,
    });
    const { status, statusText, data } = response;
    if (status === 200) {
      return data;
    }
    return {
      status,
      message: statusText,
    };
  } catch (err) {
    const { response } = err;
    const { status=500, statusText='unknown server error' } = response || {};
    return {
      status,
      message: statusText
    };
  }
}

/**
 * get session key from the path.
 */
export async function getSessionKey() {
  if (isBrowser()) {
    const value = Cookies.get(COOKIE_KEY);
    if (value) {
      const userLoginInfo = JSON.parse(value);
      const { sessionKey } = userLoginInfo;
      return sessionKey;
    }
    return null;
  }

  const sessionPath = gateway.user.sessionPath;
  const home = process.env.HOME;
  const sessionFullPath = `${home}/${sessionPath}`;
  try {
    const content = await readFile(sessionFullPath, { encoding: 'utf8' });
    const items = content.split("\n");
    const line = items.find((item) => item.startsWith("sessionKey="));
    if (line) {
      return line.replace("sessionKey=", "");
    }
  } catch (err) {
  }
  return null;
}

/**
 * @template T
 * @template {{ status: number, data: T, message: string}} Response
 * get data from url.
 * @param {string} url - the url.
 * @param {number} [timeout] - the timeout.
 * @returns {Promise<Response>} - the get result.
 */
export async function getData(url, timeout=30000) {
  try {
    const headers = {
      'Content-Type': 'application/json',
    };
    const authorization = await getSessionKey();
    if (authorization) {
      headers['AuthorizationV2'] = authorization;
    }
    const response = await axios.get(url, {
      headers,
      timeout,
    });
    const { status, statusText, data } = response;
    if (status === 200) {
      return data;
    }
    return {
      status,
      message: statusText,
    };
  } catch (err) {
    const { response } = err;
    const { status=500, statusText='unknown server error' } = response || {};
    return {
      status,
      message: statusText
    };
  }
}

export function isBrowser() {
  // Check if the environment is a
  // Service worker
  if (typeof importScripts === "function") {
    return false;
  }

  // Check if the environment is a Browser
  if (typeof window === "object") {
    return true;
  }

  // Check if the environment is Node.js
  if (typeof process === "object"
      && typeof require === "function") {
    return false;
  }

  return false;
}

export function exists(path) {
  try {
    accessSync(path, constants.R_OK | constants.W_OK);
    return true;
  } catch (_) {
    return false;
  } 
}


